package com.king.base.service.menu.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.king.base.auth.utils.EntityUtils;
import com.king.base.common.TreeSelect;
import com.king.base.domain.menu.Menu;
import com.king.base.domain.menu.vo.MenuVo;
import com.king.base.domain.menu.vo.MetaVo;
import com.king.base.exception.BadRequestException;
import com.king.base.exception.EntityExistException;
import com.king.base.mapper.menu.MenuMapper;
import com.king.base.service.menu.MenuService;
import com.king.base.service.role.RoleMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class MenuServiceImpl extends ServiceImpl<MenuMapper,Menu> implements MenuService {
    @Resource
    private RoleMenuService roleMenuService;
    /**
     * 查询系统菜单那列表
     * @param menu
     * @return
     */
    @Override
    public List<Menu> selectMenuList(Menu menu) {
        return baseMapper.selectMenuList(menu);
    }

    @Override
    public boolean saveOrUpdate(Menu entity) {
        if (checkMenuNameUnique(entity)) {
            throw new EntityExistException(Menu.class,"菜单名",entity.getMenuName());
        }
        if(StringUtils.isNotBlank(entity.getMenuId())){
            EntityUtils.setUpdatedInfo(entity);
        }else{
            EntityUtils.setCreateAndUpdateInfo(entity);
        }
        return super.saveOrUpdate(entity);
    }

    /**
     * 根据用户ID查询操作权限
     * @param userId
     * @return
     */
    @Override
    public Set<String> selectMenuPermissionByUserId(String userId) {
        List<String> list=baseMapper.selectMenuPermissionByUserId(userId);
        Set<String> permissionSet=new HashSet<>();
        list.forEach(s -> {
            if(StringUtils.isNotBlank(s)){
                permissionSet.addAll(Arrays.asList(s.trim().split(",")));
            }
        });
        return permissionSet;
    }
    /**
     * 根据用户ID构建菜单结构
     * @return
     */
    @Override
    public List<Menu> selectMenuByUserId(String userId) {
        List<Menu> menus=null;
        //如果是系统管理员，则加载全部菜单
        if("1".equalsIgnoreCase(userId)){
            menus=baseMapper.selectMenuTreeAll();
        }else{
            menus=baseMapper.selectMenuTreeByUserId(userId);
        }
        return buildChildList(menus,"0");
    }
    /**
     * 根据角色查询菜单
     * @param roleId
     * @return
     */
    @Override
    public List<String> selectMenuByRoleId(String roleId) {
        return baseMapper.selectMenuListByRoleId(roleId);
    }

    /**
     * 构建前台路由
     * @param menus
     * @return
     */
    @Override
    public List<MenuVo> buildMenuRouter(List<Menu> menus) {
        List<MenuVo> list=new ArrayList<>();
        menus.forEach(menu -> {
            list.add(buildMenuVo(menu));
        });
        return list;
    }

    /**
     * 构建前台选择器
     * @param menus
     * @return
     */
    @Override
    public List<TreeSelect> buildMenuTreeSelect(List<Menu> menus) {
        List<Menu> menuList=buildMenuTree(menus);
        return menuList.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    @Override
    public List<Menu> buildMenuTree(List<Menu> menus) {
        List<Menu> returnList = new ArrayList<Menu>();
        for (Iterator<Menu> iterator = menus.iterator(); iterator.hasNext();)
        {
            Menu t = (Menu) iterator.next();
            // 根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId().equalsIgnoreCase("0"))
            {
                recursion(menus, t);
                returnList.add(t);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 构建单个路由
     * @param menu
     * @return
     */
    private MenuVo buildMenuVo(Menu menu){
        MenuVo menuVo = new MenuVo();
        menuVo.setName(menu.getMenuName());
        menuVo.setPath(getRouterPath(menu));
        menuVo.setComponent(StringUtils.isEmpty(menu.getComponent()) ? "Layout" : menu.getComponent());
        menuVo.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(),menu.isKeepAlive()));
        menuVo.setName(menu.getMenuName());
        List<Menu> children = menu.getChildren();
        if (!children.isEmpty() && children.size() > 0 && "M".equals(menu.getMenuType()))
        {
            menuVo.setAlwaysShow(true);
            menuVo.setRedirect("noRedirect");
            menuVo.setChildren(buildMenuRouter(children));
        }
        return menuVo;
    }
    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(Menu menu)
    {
        String routerPath = menu.getPath();
        // 非外链并且是一级目录
        if ("0".equalsIgnoreCase(menu.getParentId()) && "1".equals(menu.getIsFrame()))
        {
            routerPath = "/" + menu.getPath();
        }
        return routerPath;
    }
    /**
     * 构建菜单列表
     * @param list
     * @param parentId
     * @return
     */

    private List<Menu> buildChildList(List<Menu> list,String parentId){
        List<Menu> returnList=new ArrayList<>();
        for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
        {
            Menu t = (Menu) iterator.next();
            if (t.getParentId() .equalsIgnoreCase(parentId) )
            {
                recursion(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 菜单递归
     * @param list
     * @param menu
     */
    private void recursion(List<Menu> list,Menu menu){
        List<Menu> childList=getChildList(list,menu);
        menu.setChildren(childList);
        childList.forEach(m ->{
            if(hasChild(list,m)){
                Iterator<Menu> it = childList.iterator();
                while (it.hasNext()){
                    Menu t=(Menu)it.next();
                    recursion(list,t);
                }
            }
        } );
    }

    /**
     * 获取子节点
     */
    private List<Menu> getChildList(List<Menu> list,Menu menu){
        List<Menu> menus=new ArrayList<>();
        Iterator<Menu> it=list.iterator();
        while (it.hasNext()){
            Menu m=(Menu)it.next();
            if(m.getParentId().equalsIgnoreCase(menu.getMenuId())){
                menus.add(m);
            }
        }
        return menus;
    }
    /**
     * 判断是否有子节点
     */
    private Boolean hasChild(List<Menu> list,Menu menu){
        return  getChildList(list,menu).size()>0;
    }

    public boolean checkMenuNameUnique(Menu menu){
        Menu m=baseMapper.checkMenuNameUnique(menu);
        return m!=null ;
    }

    @Override
    public boolean hasChildByMenuId(String menuId) {

        return baseMapper.hasChildByMenuId(menuId)>0;
    }

    @Override
    public void delete(String menuId) {
        if(hasChildByMenuId(menuId)){
            throw new BadRequestException("请先删除子菜单!");
        }
        if(roleMenuService.checkMenuExistRole(menuId)){
            throw new BadRequestException("菜单已分配,不允许删除");
        }
        baseMapper.deleteById(menuId);
    }
}
